import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import { LvSelectSM } from '../core/api';
import { TreeFilterConfig, TreeFilterConfig as FilterConfig, TreeNode } from './interface';

@Injectable()
export class TreeService {
  expandedNodeList: TreeNode[] = [];
  private _tree;
  private _event$ = new Subject<void>(); // 监听有事件触发的流
  private _selectionMode: LvSelectSM = 'single'; // 模式
  private _expandedNode$ = new Subject<TreeNode>(); // 节点切换展开的流
  private filterMap = new Map<string, FilterConfig>();
  private _lineChange$ = new BehaviorSubject<boolean>(false); // 触发line变更的流

  constructor() {}

  emitEvent(): void {
    this._event$.next();
  }

  getRootComponent(): any {
    return this._tree;
  }

  clearFilterState(): void {
    this.filterMap.clear();
  }

  getMode(): LvSelectSM {
    return this._selectionMode;
  }

  setRootComponent(source): void {
    this._tree = source;
  }

  setMode(value: LvSelectSM): void {
    this._selectionMode = value;
  }

  /**
   * return expanded nodes
   */
  getExpandedNodeList(): TreeNode[] {
    return this.expandedNodeList;
  }

  removeFilterState(key: string): void {
    this.filterMap.delete(key);
  }

  isMultipleMode(): boolean {
    return this._selectionMode === 'multiple';
  }

  subscribeEvent(): Observable<any> {
    return this._event$.asObservable();
  }

  getFilterState(): Map<string, TreeFilterConfig> {
    return this.filterMap;
  }

  /**
   * 广播展开节点
   */
  setExpandedStream(source: TreeNode): void {
    this._expandedNode$.next(source);
  }

  /**
   * filter
   */
  setFilterState(data: FilterConfig): void {
    this.filterMap.set(data.key, data);
  }

  getExpandedStream(): Observable<any> {
    return this._expandedNode$.asObservable();
  }

  getLineChangeStream(): Observable<boolean> {
    return this._lineChange$.pipe(filter((res): boolean => res));
  }

  /**
   * New functions for flatten nodes
   */
  getIndexOfArray(list: TreeNode[], key: string): number {
    return list.findIndex((v): boolean => v.key === key);
  }

  /**
   * 广播数据更新触发line
   */
  setLineChangeStream(data: TreeNode[]): void {
    let status = false;
    if (!data || !data.length) {
      status = false;
    }
    status = data.some((item): any | boolean => item.expanded);
    return this._lineChange$.next(status);
  }

  /**
   * set expanded nodes
   */
  setExpandedNodeList(node: TreeNode): void {
    if (node.isLeaf) {
      return;
    }
    const index = this.getIndexOfArray(this.expandedNodeList, node.key);
    if (node.expanded && index === -1) {
      this.expandedNodeList.push(node);
    } else if (!node.expanded && index > -1) {
      this.expandedNodeList.splice(index, 1);
    }
  }
}
